<?php
namespace WDB\Ajax;
use WDB;

/**
 * Server-side form validator verifying that a record identified by _REQUEST['record'] won't violate
 * any unique constraint in a table _REQUEST['table']
 * 
 * Arguments:
 * table   : db table locator string (@see WDB\Structure\TableLocator)
 * record  : original record string key (or none if new record)
 * keys    : array of all unique keys Key name=>Key data
 * keys[k][implicit] : list of names of columns which are part of the key, but are NOT being currently edited. Their value is not
 *                     known from the form, it must be re-read from the database.
 * keys[k][explicit] : associative array of (column name)=>value pairs of all columns in the key that ARE being currently edited.
 * 
 *
 * @author Richard Ejem <richard(at)ejem.cz>
 * @package WDB
 */
class UniqueValidator implements iHandler
{
    public function handle()
    {
        $table = WDB\Wrapper\TableFactory::fromLocator(new WDB\Structure\TableLocator($_REQUEST['table']));
        $columns = $table->getColumns();
        if (empty($_REQUEST['record']) || (isset($_REQUEST['recordIsNull']) && $_REQUEST['recordIsNull'] == 1))
        {
            $record = NULL;
        }
        else
        {
            $record = $table->getRecordByStringPK($_REQUEST['record']);
        }
        
        $violated = array();
        foreach ($_REQUEST['keys'] as $keyIdent=>$key)
        {
            $searchKey = array();
            if (isset($key['explicit']))
            {
                foreach ($key['explicit'] as $k=>$v)
                {
                    $searchKey[$k] = isset($columns[$k]) ? $columns[$k]->setFieldValue($v) : $v;
                }
            }
            else
            {
                continue; //all keys are implicit - doesn`t make sense to validate
            }
            if (isset($key['implicit']))
            {
                if ($record !== NULL)
                {
                    foreach ($key['implicit'] as $k)
                    {
                        $searchKey[$k] = $record[$k];
                    }
                }
                else
                {
                    foreach ($key['implicit'] as $k)
                    {
                        $searchKey[$k] = $table->columns[$k]->getDefault();
                    }
                }
            }
            //add condition
            $q = $table->getDatasource()->filter($searchKey);
            if ($record !== NULL)
            {
                $q = $q->not($record->getIdentificationKey());
            }
            if ($q->count())
            {
                reset($searchKey);
                if (count($searchKey) > 1)
                {
                    $titles = array();
                    foreach (array_keys($searchKey) as $col)
                    {
                        $titles[] = $columns[$col]->getTitle();
                    }
                    $msg = str_replace('%fieldlist', implode(', ', $titles), WDB\Lang::s('validator.messages.uniqueGroupViolated'));
                }
                else
                {
                    $msg = str_replace('%name', $columns[key($searchKey)]->getTitle(), WDB\Lang::s('validator.messages.uniqueViolated'));
                }
                $violated[] = array('key'=>$keyIdent, 'message'=>$msg);
            }
        }
        return array('success'=>count($violated) == 0, 'violated'=>$violated);
    }
}
